fix(tracing): correct otel thread context for active contexts, sampling and switches - #19704
fix(tracing): correct otel thread context for active contexts, sampling and switches#19704florentinl wants to merge 2 commits into
Conversation
…ng and switches Three correctness issues in the OTel thread-context publisher: - An active Context published nothing. It was treated as "no trace", but a Context is a span the execution runs inside without owning it -- a remote parent, or the submitter of offloaded work -- so all executor worker threads reported no trace. Adds update_otel_thread_context_ids for the case where there is no SpanData to read ids off. - The switch listener called active(), which repairs the contextvar and re-dispatches the activate event. From a CPython context-switch watcher that writes to whichever context the switch just made current and publishes twice for one switch. The finished-span walk moves into a shared resolve_active, and a new _peek_active reports it without applying it; active() keeps its repair. - trace_flags never reflected the sampling decision, which normally lands at trace-chunk finish, long after the record was published. The Context.sampling_priority setter now dispatches an event the publisher resyncs on.
Codeowners resolved asResolved from the full PR diff against |
Circular import analysis
|
Dependency direction analysis
|
|
…e read-only peek _peek_active guarded on the exact DefaultContextProvider type, so a subclass that overrides nothing relevant -- tornado's TracerStackContext, which is installed on the global tracer -- fell back to the mutating active(). The guard is replaced by the requirement that providers with their own storage override _peek_active, which CIContextProvider and LLMObsContextProvider now do explicitly.
BenchmarksBenchmark execution time: 2026-08-14 15:20:26 Comparing candidate commit b48acd9 in PR branch Found 0 performance improvements and 7 performance regressions! Performance is the same for 606 metrics, 10 unstable metrics.
|
Description
Three correctness fixes to the OTel thread-context publisher:
Contextpublished nothing, so executor worker threads reported no trace fortheir whole lifetime. Now published.
active(), which repairs the contextvar and re-dispatchesthe activate event — mutating async context state mid-switch and publishing twice per switch.
It now uses a read-only
_peek_active().trace_flagsnever reflected the sampling decision, which lands long after the record ispublished, so locally-initiated traces stayed marked unsampled. Now republished on the decision.
Costs
active()+1.7 ns (per span finish) andContext.sampling_priorityTesting
Risks
Worker threads that used to publish nothing now publish the submitting span.
Additional Notes